<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>常用的事件方法(Common event methods)</title>
  <!-- 
  在JavaScript中，事件是用户与网页交互的基础。处理事件时，有一些常用的事件方法可以帮助开发者更有效地管理和响应事件。
  一、事件处理方法
  1. addEventListener()：
    - 用于向指定元素添加事件处理程序。可以添加多个事件处理程序，并可以指定事件的捕获和冒泡阶段。
    - 语法：element.addEventListener(event, function, useCapture);
    const button = document.getElementById('myButton');
    button.addEventListener('click', function() {
      alert('按钮被点击了！');
    });
  2. removeEventListener()：
    - 用于移除已添加的事件处理程序。必须传入与添加时相同的事件类型和处理函数。
    - 语法：element.removeEventListener(event, function, useCapture);
    function handleClick() {
      alert('按钮被点击了！');
    }

    button.addEventListener('click', handleClick);
    // 移除事件处理程序
    button.removeEventListener('click', handleClick);
  3. dispatchEvent()：
    - 用于手动触发某个事件。可以用来模拟用户的行为。
    - 语法：element.dispatchEvent(event);
    const event = new Event('myCustomEvent');
    button.dispatchEvent(event);

  二、事件对象
  当事件被触发时，事件处理程序会接收到一个事件对象，包含了与事件相关的信息。常用的事件对象属性和方法包括：
  1. event.target：
    - 返回触发事件的元素。
    button.addEventListener('click', function(event) {
      console.log(event.target); // 输出被点击的元素
    });
  2. event.type：
    - 返回事件的类型，例如 'click'、'keydown' 等。
    button.addEventListener('click', function(event) {
      console.log(event.type); // 输出 'click'
    });
  3. event.preventDefault()：
    - 阻止事件的默认行为。例如，阻止链接跳转或表单提交。
    const link = document.getElementById('myLink');
    link.addEventListener('click', function(event) {
      event.preventDefault(); // 阻止链接跳转
      console.log('链接被点击，但不会跳转！');
    });
  4. event.stopPropagation()：
    - 阻止事件冒泡，即不将事件传递到父元素。
    const parent = document.getElementById('parent');
    const child = document.getElementById('child');

    parent.addEventListener('click', function() {
        console.log('父元素被点击');
    });

    child.addEventListener('click', function(event) {
        event.stopPropagation(); // 阻止事件冒泡
        console.log('子元素被点击');
    });
  5. 事件委托
    - 将事件监听器添加到父元素上，而不是每个子元素上。当子元素触发事件时，事件会冒泡到父元素，父元素的事件监听器会处理该事件。
    const parent = document.getElementById('parent');
    parent.addEventListener('click', function(event) {
      if (event.target.tagName === 'BUTTON') {
        console.log('按钮被点击');
      }
    });

  三、总结
  - 常用的事件方法包括 addEventListener()、removeEventListener()、dispatchEvent()。
  - 事件对象提供了丰富的信息和控制方法，如 event.target、event.type、event.preventDefault() 和 event.stopPropagation()。
   -->
  <style>
    .parent {
      width: 230px;
      height: 230px;
      background-color: pink;
    }

    .child {
      margin: 0 auto;
      width: 160px;
      height: 160px;
      background-color: palegoldenrod;
    }

    .grandchild {
      margin: 0 auto;
      width: 100px;
      height: 100px;
      background-color: aquamarine;
    }
  </style>
</head>
<body>

  <h3>1.事件处理方法</h3>
  <button class="addEventListener-click">addEventListener-click</button>
  <button class="removeEventListener-click">removeEventListener-click</button>

  <h3>2.事件对象</h3>
  <button onclick="handleClick(event)">事件对象按钮</button>

  <h3>3.阻止默认行为</h3>
  <a href="https://www.baidu.com" class="preventDefault">链接</a>

  <h3>4.事件冒泡(bubbling)和事件捕获(capture)</h3>
  <div class="parent">
    父元素
    <div class="child">
      子元素
      <div class="grandchild">元素</div>
    </div>
  </div>

  <h3>5.事件委托(delegate)</h3>
  <ul class="event-delegate">
    <li><button>delegate1</button></li>
    <li><button>delegate2</button></li>
    <li><button>delegate3</button></li>
  </ul>
 

  <script>

    // 1.事件处理方法
    const addBtnEl = document.querySelector('.addEventListener-click');
    const removeBtnEl = document.querySelector('.removeEventListener-click');

    function handleClick() {
      console.log('按钮被点击');
    }

    addBtnEl.addEventListener('click', handleClick);
    removeBtnEl.addEventListener('click', function() {
      addBtnEl.removeEventListener('click', handleClick);
    })

    // 2.事件对象
    function handleClick(event) {
      console.log('事件对象:', event);
      console.log('事件类型:', event.type);
      console.log('事件目标:', event.target);
    }

    // 3.阻止默认行为
    const preventDefaultEl = document.querySelector('.preventDefault');
    preventDefaultEl.addEventListener('click', function(event) {
      event.preventDefault(); // 阻止默认行为
      console.log('event.preventDefault() - 阻止默认行为;链接被点击，但不会跳转！');
    })

    // 4. 事件冒泡和事件捕获
    // 4.1 阻止事件冒泡
    const parentEl = document.querySelector('.parent');
    const childEl = document.querySelector('.child');
    const grandchildEl = document.querySelector('.grandchild');

    parentEl.addEventListener('click', function() {
      console.log('stopPropagation-parentEl - 父元素事件冒泡');
    })

    childEl.addEventListener('click', function(event) {
      console.log('stopPropagation-childEl - 子元素事件冒泡');
      // event.stopPropagation(); // 阻止事件冒泡
    })

    grandchildEl.addEventListener('click', function() {
      console.log('stopPropagation-grandchildEl - 元素事件冒泡');
    })

    // 4.2 事件捕获
    parentEl.addEventListener('click', function() {
      console.log('capture-parentEl - 父元素-事件捕获');
    }, true)

    childEl.addEventListener('click', function() {
      console.log('capture-childEl - 子元素-事件捕获');
    }, true)

    grandchildEl.addEventListener('click', function() {
      console.log('capture-grandchildEl - 元素-事件捕获');
    }, true)

    // 5. 事件委托
    const ulEl = document.querySelector('ul');
    ulEl.addEventListener('click', function(event) {
      console.log('event.target', event.target);
      console.log('event.target.tagName', event.target.tagName);
      console.log('event.target.innerText', event.target.innerText);
      console.log('event.currentTarget', event.currentTarget);
    })
  </script>
  
</body>
</html>